//
// Copyright (C) [2020] Futurewei Technologies, Inc.
//
// FORCE-RISCV is licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR
// FIT FOR A PARTICULAR PURPOSE.
// See the License for the specific language governing permissions and
// limitations under the License.
//

/*  !!! NOTICE !!!
    This file is automatically generated by the script: utils/enum_classes/create_enum_files.py
    Please do not modify this file manually.  Instead, modify the above mentioned script to re-generate this file.
*/

#include <lest/lest.hpp>
#include <Log.h>

#include <EnumsFPIX.h>
#include <GenException.h>

using text = std::string;
using namespace Force;

const lest::test specification[] = {


CASE( "tests for ESimThreadEventType" ) {

  SETUP ( "setup ESimThreadEventType" )  {

    SECTION( "test enum to string conversion" ) {
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::START_TEST) == "START_TEST");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::END_TEST) == "END_TEST");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::RESET) == "RESET");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::BOOT_CODE) == "BOOT_CODE");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::FIRST_INSTRUCTION) == "FIRST_INSTRUCTION");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::PRE_STEP) == "PRE_STEP");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::STEP) == "STEP");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::POST_STEP) == "POST_STEP");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::MEMORY_UPDATE) == "MEMORY_UPDATE");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::MMU_EVENT) == "MMU_EVENT");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::REGISTER_UPDATE) == "REGISTER_UPDATE");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::DELAY) == "DELAY");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::INTERRUPT) == "INTERRUPT");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::EXCEPTION_EVENT) == "EXCEPTION_EVENT");
      EXPECT(ESimThreadEventType_to_string(ESimThreadEventType::UNKNOWN_EVENT) == "UNKNOWN_EVENT");
    }

    SECTION( "test string to enum conversion" ) {
      EXPECT(string_to_ESimThreadEventType("START_TEST") == ESimThreadEventType::START_TEST);
      EXPECT(string_to_ESimThreadEventType("END_TEST") == ESimThreadEventType::END_TEST);
      EXPECT(string_to_ESimThreadEventType("RESET") == ESimThreadEventType::RESET);
      EXPECT(string_to_ESimThreadEventType("BOOT_CODE") == ESimThreadEventType::BOOT_CODE);
      EXPECT(string_to_ESimThreadEventType("FIRST_INSTRUCTION") == ESimThreadEventType::FIRST_INSTRUCTION);
      EXPECT(string_to_ESimThreadEventType("PRE_STEP") == ESimThreadEventType::PRE_STEP);
      EXPECT(string_to_ESimThreadEventType("STEP") == ESimThreadEventType::STEP);
      EXPECT(string_to_ESimThreadEventType("POST_STEP") == ESimThreadEventType::POST_STEP);
      EXPECT(string_to_ESimThreadEventType("MEMORY_UPDATE") == ESimThreadEventType::MEMORY_UPDATE);
      EXPECT(string_to_ESimThreadEventType("MMU_EVENT") == ESimThreadEventType::MMU_EVENT);
      EXPECT(string_to_ESimThreadEventType("REGISTER_UPDATE") == ESimThreadEventType::REGISTER_UPDATE);
      EXPECT(string_to_ESimThreadEventType("DELAY") == ESimThreadEventType::DELAY);
      EXPECT(string_to_ESimThreadEventType("INTERRUPT") == ESimThreadEventType::INTERRUPT);
      EXPECT(string_to_ESimThreadEventType("EXCEPTION_EVENT") == ESimThreadEventType::EXCEPTION_EVENT);
      EXPECT(string_to_ESimThreadEventType("UNKNOWN_EVENT") == ESimThreadEventType::UNKNOWN_EVENT);
    }

    SECTION( "test string to enum conversion with non-matching string" ) {
      EXPECT_THROWS_AS(string_to_ESimThreadEventType("S_ART_TEST"), EnumTypeError);
    }

    SECTION( "test non-throwing string to enum conversion" ) {
      bool okay = false;
      EXPECT(try_string_to_ESimThreadEventType("START_TEST", okay) == ESimThreadEventType::START_TEST);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("END_TEST", okay) == ESimThreadEventType::END_TEST);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("RESET", okay) == ESimThreadEventType::RESET);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("BOOT_CODE", okay) == ESimThreadEventType::BOOT_CODE);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("FIRST_INSTRUCTION", okay) == ESimThreadEventType::FIRST_INSTRUCTION);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("PRE_STEP", okay) == ESimThreadEventType::PRE_STEP);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("STEP", okay) == ESimThreadEventType::STEP);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("POST_STEP", okay) == ESimThreadEventType::POST_STEP);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("MEMORY_UPDATE", okay) == ESimThreadEventType::MEMORY_UPDATE);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("MMU_EVENT", okay) == ESimThreadEventType::MMU_EVENT);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("REGISTER_UPDATE", okay) == ESimThreadEventType::REGISTER_UPDATE);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("DELAY", okay) == ESimThreadEventType::DELAY);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("INTERRUPT", okay) == ESimThreadEventType::INTERRUPT);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("EXCEPTION_EVENT", okay) == ESimThreadEventType::EXCEPTION_EVENT);
      EXPECT(okay);
      EXPECT(try_string_to_ESimThreadEventType("UNKNOWN_EVENT", okay) == ESimThreadEventType::UNKNOWN_EVENT);
      EXPECT(okay);
    }

    SECTION( "test non-throwing string to enum conversion with non-matching string" ) {
      bool okay = false;
      try_string_to_ESimThreadEventType("S_ART_TEST", okay);
      EXPECT(!okay);
    }
  }
},


CASE( "tests for EOptionIndex" ) {

  SETUP ( "setup EOptionIndex" )  {

    SECTION( "test enum to string conversion" ) {
      EXPECT(EOptionIndex_to_string(EOptionIndex::UNKNOWN) == "UNKNOWN");
      EXPECT(EOptionIndex_to_string(EOptionIndex::CFG) == "CFG");
      EXPECT(EOptionIndex_to_string(EOptionIndex::HELP) == "HELP");
      EXPECT(EOptionIndex_to_string(EOptionIndex::LOGLEVEL) == "LOGLEVEL");
      EXPECT(EOptionIndex_to_string(EOptionIndex::SEED) == "SEED");
      EXPECT(EOptionIndex_to_string(EOptionIndex::MAX_INSTS_OPT) == "MAX_INSTS_OPT");
      EXPECT(EOptionIndex_to_string(EOptionIndex::RAILHOUSE_OPT) == "RAILHOUSE_OPT");
      EXPECT(EOptionIndex_to_string(EOptionIndex::DECODING_OPT) == "DECODING_OPT");
      EXPECT(EOptionIndex_to_string(EOptionIndex::CORE_NUM_OPT) == "CORE_NUM_OPT");
      EXPECT(EOptionIndex_to_string(EOptionIndex::CLUSTER_NUM_OPT) == "CLUSTER_NUM_OPT");
      EXPECT(EOptionIndex_to_string(EOptionIndex::THREADS_PER_CPU_OPT) == "THREADS_PER_CPU_OPT");
      EXPECT(EOptionIndex_to_string(EOptionIndex::PA_SIZE_OPT) == "PA_SIZE_OPT");
      EXPECT(EOptionIndex_to_string(EOptionIndex::EXIT_LOOP_OPT) == "EXIT_LOOP_OPT");
      EXPECT(EOptionIndex_to_string(EOptionIndex::PLUGIN) == "PLUGIN");
      EXPECT(EOptionIndex_to_string(EOptionIndex::PLUGINS_OPTIONS) == "PLUGINS_OPTIONS");
    }

    SECTION( "test string to enum conversion" ) {
      EXPECT(string_to_EOptionIndex("UNKNOWN") == EOptionIndex::UNKNOWN);
      EXPECT(string_to_EOptionIndex("CFG") == EOptionIndex::CFG);
      EXPECT(string_to_EOptionIndex("HELP") == EOptionIndex::HELP);
      EXPECT(string_to_EOptionIndex("LOGLEVEL") == EOptionIndex::LOGLEVEL);
      EXPECT(string_to_EOptionIndex("SEED") == EOptionIndex::SEED);
      EXPECT(string_to_EOptionIndex("MAX_INSTS_OPT") == EOptionIndex::MAX_INSTS_OPT);
      EXPECT(string_to_EOptionIndex("RAILHOUSE_OPT") == EOptionIndex::RAILHOUSE_OPT);
      EXPECT(string_to_EOptionIndex("DECODING_OPT") == EOptionIndex::DECODING_OPT);
      EXPECT(string_to_EOptionIndex("CORE_NUM_OPT") == EOptionIndex::CORE_NUM_OPT);
      EXPECT(string_to_EOptionIndex("CLUSTER_NUM_OPT") == EOptionIndex::CLUSTER_NUM_OPT);
      EXPECT(string_to_EOptionIndex("THREADS_PER_CPU_OPT") == EOptionIndex::THREADS_PER_CPU_OPT);
      EXPECT(string_to_EOptionIndex("PA_SIZE_OPT") == EOptionIndex::PA_SIZE_OPT);
      EXPECT(string_to_EOptionIndex("EXIT_LOOP_OPT") == EOptionIndex::EXIT_LOOP_OPT);
      EXPECT(string_to_EOptionIndex("PLUGIN") == EOptionIndex::PLUGIN);
      EXPECT(string_to_EOptionIndex("PLUGINS_OPTIONS") == EOptionIndex::PLUGINS_OPTIONS);
    }

    SECTION( "test string to enum conversion with non-matching string" ) {
      EXPECT_THROWS_AS(string_to_EOptionIndex("U_KNOWN"), EnumTypeError);
    }

    SECTION( "test non-throwing string to enum conversion" ) {
      bool okay = false;
      EXPECT(try_string_to_EOptionIndex("UNKNOWN", okay) == EOptionIndex::UNKNOWN);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("CFG", okay) == EOptionIndex::CFG);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("HELP", okay) == EOptionIndex::HELP);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("LOGLEVEL", okay) == EOptionIndex::LOGLEVEL);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("SEED", okay) == EOptionIndex::SEED);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("MAX_INSTS_OPT", okay) == EOptionIndex::MAX_INSTS_OPT);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("RAILHOUSE_OPT", okay) == EOptionIndex::RAILHOUSE_OPT);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("DECODING_OPT", okay) == EOptionIndex::DECODING_OPT);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("CORE_NUM_OPT", okay) == EOptionIndex::CORE_NUM_OPT);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("CLUSTER_NUM_OPT", okay) == EOptionIndex::CLUSTER_NUM_OPT);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("THREADS_PER_CPU_OPT", okay) == EOptionIndex::THREADS_PER_CPU_OPT);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("PA_SIZE_OPT", okay) == EOptionIndex::PA_SIZE_OPT);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("EXIT_LOOP_OPT", okay) == EOptionIndex::EXIT_LOOP_OPT);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("PLUGIN", okay) == EOptionIndex::PLUGIN);
      EXPECT(okay);
      EXPECT(try_string_to_EOptionIndex("PLUGINS_OPTIONS", okay) == EOptionIndex::PLUGINS_OPTIONS);
      EXPECT(okay);
    }

    SECTION( "test non-throwing string to enum conversion with non-matching string" ) {
      bool okay = false;
      try_string_to_EOptionIndex("U_KNOWN", okay);
      EXPECT(!okay);
    }
  }
},


CASE( "tests for EOperandType" ) {

  SETUP ( "setup EOperandType" )  {

    SECTION( "test enum to string conversion" ) {
      EXPECT(EOperandType_to_string(EOperandType::Register) == "Register");
      EXPECT(EOperandType_to_string(EOperandType::GPR) == "GPR");
      EXPECT(EOperandType_to_string(EOperandType::VECREG) == "VECREG");
    }

    SECTION( "test string to enum conversion" ) {
      EXPECT(string_to_EOperandType("Register") == EOperandType::Register);
      EXPECT(string_to_EOperandType("GPR") == EOperandType::GPR);
      EXPECT(string_to_EOperandType("VECREG") == EOperandType::VECREG);
    }

    SECTION( "test string to enum conversion with non-matching string" ) {
      EXPECT_THROWS_AS(string_to_EOperandType("R_gister"), EnumTypeError);
    }

    SECTION( "test non-throwing string to enum conversion" ) {
      bool okay = false;
      EXPECT(try_string_to_EOperandType("Register", okay) == EOperandType::Register);
      EXPECT(okay);
      EXPECT(try_string_to_EOperandType("GPR", okay) == EOperandType::GPR);
      EXPECT(okay);
      EXPECT(try_string_to_EOperandType("VECREG", okay) == EOperandType::VECREG);
      EXPECT(okay);
    }

    SECTION( "test non-throwing string to enum conversion with non-matching string" ) {
      bool okay = false;
      try_string_to_EOperandType("R_gister", okay);
      EXPECT(!okay);
    }
  }
},


CASE( "tests for EAccessAgeType" ) {

  SETUP ( "setup EAccessAgeType" )  {

    SECTION( "test enum to string conversion" ) {
      EXPECT(EAccessAgeType_to_string(EAccessAgeType::Invalid) == "Invalid");
      EXPECT(EAccessAgeType_to_string(EAccessAgeType::Read) == "Read");
      EXPECT(EAccessAgeType_to_string(EAccessAgeType::Write) == "Write");
    }

    SECTION( "test string to enum conversion" ) {
      EXPECT(string_to_EAccessAgeType("Invalid") == EAccessAgeType::Invalid);
      EXPECT(string_to_EAccessAgeType("Read") == EAccessAgeType::Read);
      EXPECT(string_to_EAccessAgeType("Write") == EAccessAgeType::Write);
    }

    SECTION( "test string to enum conversion with non-matching string" ) {
      EXPECT_THROWS_AS(string_to_EAccessAgeType("I_valid"), EnumTypeError);
    }

    SECTION( "test non-throwing string to enum conversion" ) {
      bool okay = false;
      EXPECT(try_string_to_EAccessAgeType("Invalid", okay) == EAccessAgeType::Invalid);
      EXPECT(okay);
      EXPECT(try_string_to_EAccessAgeType("Read", okay) == EAccessAgeType::Read);
      EXPECT(okay);
      EXPECT(try_string_to_EAccessAgeType("Write", okay) == EAccessAgeType::Write);
      EXPECT(okay);
    }

    SECTION( "test non-throwing string to enum conversion with non-matching string" ) {
      bool okay = false;
      try_string_to_EAccessAgeType("I_valid", okay);
      EXPECT(!okay);
    }
  }
},


CASE( "tests for EDependencyType" ) {

  SETUP ( "setup EDependencyType" )  {

    SECTION( "test enum to string conversion" ) {
      EXPECT(EDependencyType_to_string(EDependencyType::OnSource) == "OnSource");
      EXPECT(EDependencyType_to_string(EDependencyType::OnTarget) == "OnTarget");
    }

    SECTION( "test string to enum conversion" ) {
      EXPECT(string_to_EDependencyType("OnSource") == EDependencyType::OnSource);
      EXPECT(string_to_EDependencyType("OnTarget") == EDependencyType::OnTarget);
    }

    SECTION( "test string to enum conversion with non-matching string" ) {
      EXPECT_THROWS_AS(string_to_EDependencyType("O_Source"), EnumTypeError);
    }

    SECTION( "test non-throwing string to enum conversion" ) {
      bool okay = false;
      EXPECT(try_string_to_EDependencyType("OnSource", okay) == EDependencyType::OnSource);
      EXPECT(okay);
      EXPECT(try_string_to_EDependencyType("OnTarget", okay) == EDependencyType::OnTarget);
      EXPECT(okay);
    }

    SECTION( "test non-throwing string to enum conversion with non-matching string" ) {
      bool okay = false;
      try_string_to_EDependencyType("O_Source", okay);
      EXPECT(!okay);
    }
  }
},

};

int main(int argc, char* argv[])
{
  Logger::Initialize();
  int ret = lest::run(specification, argc, argv);
  Logger::Destroy();
  return ret;
}
